#pragma once
#include "Node.h"
#include "xKernel/IxView.h"
#include "xKernel/IxPaint.h"
#include "xKernel/IxBorderPaint.h"
#include "xKernel/IxFocusPaint.h"
#include "xKernel/IxSchedule.h"
#include "xKernel/IxCanvas.h"
#include "xKernel/IxDraw.h"

class CxView
    : public CxNode
    , public IxView
    , public IxPaint
    , public IxBorderPaint
    , public IxFocusPaint
    , public IxSchedule
{
    typedef CComPtr<IxDraw> DRAW;

public:
    CxView();
    virtual ~CxView();

    // interface of IxView
    HRESULT STDMETHODCALLTYPE GetLayoutType(LPINT pnType);
    HRESULT STDMETHODCALLTYPE SetLayoutType(INT nType);

    HRESULT STDMETHODCALLTYPE GetBoxRect(LPRECT lprcBox);
    HRESULT STDMETHODCALLTYPE SetBoxRect(RECT rcBox);

    HRESULT STDMETHODCALLTYPE GetSize(LPSIZE lpszSize);
    HRESULT STDMETHODCALLTYPE SetSize(SIZE szSize);

    HRESULT STDMETHODCALLTYPE GetPosition(LPPOINT pptPos);
    HRESULT STDMETHODCALLTYPE SetPosition(POINT ptPos);

    HRESULT STDMETHODCALLTYPE GetMargin(LPRECT lprcMargin);
    HRESULT STDMETHODCALLTYPE SetMargin(RECT rcMargin);

    HRESULT STDMETHODCALLTYPE GetPadding(LPRECT lprcPadding);
    HRESULT STDMETHODCALLTYPE SetPadding(RECT rcPadding);

    HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprcBorder);
    HRESULT STDMETHODCALLTYPE SetBorder(RECT rcBorder);

    HRESULT STDMETHODCALLTYPE GetBorderColor(LPCOLORREF lpclrBorder);
    HRESULT STDMETHODCALLTYPE SetBorderColor(COLORREF clrBorder);

    HRESULT STDMETHODCALLTYPE GetAlignment(LPINT pnAlignment);
    HRESULT STDMETHODCALLTYPE SetAlignment(INT nAlignment);

    HRESULT STDMETHODCALLTYPE GetState(LPINT pnState);
    HRESULT STDMETHODCALLTYPE SetState(INT nState);

    HRESULT STDMETHODCALLTYPE GetAlpha(LPBYTE pbyAlpha);
    HRESULT STDMETHODCALLTYPE SetAlpha(BYTE byAlpha);

    HRESULT STDMETHODCALLTYPE GetZOrder(LPINT pnZorder);
    HRESULT STDMETHODCALLTYPE SetZOrder(INT nZorder);

    HRESULT STDMETHODCALLTYPE GetCheck(LPBOOL pbCheck);
    HRESULT STDMETHODCALLTYPE SetCheck(BOOL bCheck);

    HRESULT STDMETHODCALLTYPE GetEnable(LPBOOL pbEnable);
    HRESULT STDMETHODCALLTYPE SetEnable(BOOL bEnable);

    HRESULT STDMETHODCALLTYPE GetNormalDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetNormalDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetHighlightDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetHighlightDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetPushDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetPushDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetDisableDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetDisableDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetCheckNormalDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetCheckNormalDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetCheckHighlightDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetCheckHighlightDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetCheckPushDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetCheckPushDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetCheckDisableDraw(IxDraw** ppDraw);
    HRESULT STDMETHODCALLTYPE SetCheckDisableDraw(IxDraw* pDraw);

    HRESULT STDMETHODCALLTYPE GetShowState(LPBOOL pbShow);
    HRESULT STDMETHODCALLTYPE SetShowState(BOOL bShow);

    HRESULT STDMETHODCALLTYPE GetVisibleState(LPBOOL pbVisible);

    HRESULT STDMETHODCALLTYPE SetFocusState(BOOL bFocus);
    HRESULT STDMETHODCALLTYPE GetFocusState(LPBOOL pbFocus);

    HRESULT STDMETHODCALLTYPE GetVisibleRect(LPRECT lprcVisible);
    HRESULT STDMETHODCALLTYPE GetAbsoluteRect(LPRECT lprcAbsolute);

    HRESULT STDMETHODCALLTYPE HitTest(POINT pt, LPBOOL pbIn);

    // interface of IxPaint
    HRESULT STDMETHODCALLTYPE Paint(IxCanvas* pCanvas);

    // interface of IxBorderPaint
    HRESULT STDMETHODCALLTYPE BorderPaint(IxCanvas* pCanvas);

    // interface of IxFocusPaint
    HRESULT STDMETHODCALLTYPE FocusPaint(IxCanvas* pCanvas);

    //interface of IxMessageReceive
    HRESULT STDMETHODCALLTYPE OnMessage(LPEVENTPARAM params, LPBOOL pbHandled);

    // interface of IxSchedule
    HRESULT STDMETHODCALLTYPE ScheduleLayout(IxView* pView);
    HRESULT STDMETHODCALLTYPE SchedulePaint(IxView* pView);
    HRESULT STDMETHODCALLTYPE Invalidate(RECT rcDirty);

    // interface of IxElement
    HRESULT STDMETHODCALLTYPE SetAttribute(IxPairVec* pAttriVec);

protected:
    HRESULT _get_draw_by_state(INT nState, bool bCheck, IxDraw** ppDraw);

    HRESULT _set_box_rect(RECT& rcBox);

    bool    _is_checked()
    {
        return ((m_nState & E_STATE_CHECK_MASK) == E_STATE_CHECK);
    }

    INT     _get_paind_index()
    {
        return ((m_nState & E_STATE_ENABLE) ? (m_nState & E_STATE_MASK) : (E_STATE_COUNT));
    }

protected:
    INT         m_nLayoutType;
    INT         m_nAlignment;
    INT         m_nZOrder;
    INT         m_nState;
    CRect       m_rcBox;
    CRect       m_rcMargin;
    CRect       m_rcPadding;
    CRect       m_rcBorder;
    COLORREF    m_clrBorder;
    DRAW        m_pDraw[E_STATE_COUNT + 1];
    DRAW        m_pDrawCheck[E_STATE_COUNT + 1];
    BYTE        m_byAlpha;
    bool        m_bShow;
    bool        m_bFocus;

#if _DEBUG
    INT     __count;
#endif
};

[
    default(IxView),
    threading(free),
    uuid("427C8C00-C215-4d08-A459-ADF53E08186C"),
    coclass
]
class CCoView : public CxView
{
public:
    DECLARE_PROTECT_FINAL_CONSTRUCT()
    DECLARE_GET_CONTROLLING_UNKNOWN()

    BEGIN_COM_MAP(CCoView)
        VIEW_INTERFACE()
    END_COM_MAP()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {}
};